#ifndef __ILIB_CORE_TIMER_THREAD_20120413__
#define __ILIB_CORE_TIMER_THREAD_20120413__

#include "../../iHeader.h"
#include "../h/iThreadMgr.h"
#include "../h/iTimer.h"
#include "iMsgThread.h"

#define MSG_ADD_TIMER	2012

class iTimerWheel
{
public:
	iTimerWheel()
	{
        m_meter[0].set_timer_wheel(this);
        m_meter[1].set_timer_wheel(this);
        m_meter[2].set_timer_wheel(this);
        m_meter[3].set_timer_wheel(this);

		m_meter[0].chain(m_meter[1]);
		m_meter[1].chain(m_meter[2]);
		m_meter[2].chain(m_meter[3]);
	}
	void add_timer(iTimer* tmr, uint32_t jiffies)
	{
		//printf("jiffies=%d,c1=%d,c2=%d,c3=%d,c4=%d\n", jiffies,m_meter[0].get_cursor(), m_meter[1].get_cursor(),m_meter[2].get_cursor(),m_meter[3].get_cursor());
		if(jiffies & 0xFF000000)
		{
			m_meter[3].put(tmr, jiffies>>24,(jiffies&0x00FFFFFF)
                                            +(uint32_t)m_meter[0].get_cursor()
                                            +(((uint32_t)m_meter[1].get_cursor())<<8)
                                            +(((uint32_t)m_meter[2].get_cursor())<<8)
                                            );
		}
		else if(jiffies & 0x00FF0000)
		{
			m_meter[2].put(tmr, jiffies>>16,(jiffies&0x0000FFFF)
                                            +(uint32_t)m_meter[0].get_cursor()
                                            +(((uint32_t)m_meter[1].get_cursor())<<8)
                                            );
		}
		else if(jiffies & 0x0000FF00)
		{
			m_meter[1].put(tmr, jiffies>>8, (jiffies&0x000000FF)
                                            +m_meter[0].get_cursor()
                                            );
		}
		else
			m_meter[0].put(tmr, jiffies, 0);
	}
	inline void jiffy()
	{
		m_meter[0].jiffy();
	}

private:
	struct iTimerObject
	{
		struct iTimerObjectEntry { iTimer* tmr; uint32_t metrics; };
		std::list<iTimerObjectEntry>	m_timers;
	};

	class iTimerMeter
	{
	public:
		iTimerMeter()
			: m_cursor(0)
			, m_next(NULL)
		{

		}
		inline void set_timer_wheel(iTimerWheel* tw)
		{
			m_timer_wheel = tw;
		}
		inline iTimerWheel* get_timer_wheel() 
		{ 
			return m_timer_wheel; 
		}
        inline uint32_t get_cursor() 
        {
            return m_cursor;
        }
		inline iTimerMeter* chain(iTimerMeter& next)
		{
			iTimerMeter* pre = m_next;
			m_next = &next;
			return pre;
		}
		inline void jiffy() 
		{
			m_cursor++;
			if(m_cursor==0 && m_next)
				m_next->jiffy();

            if(m_to[m_cursor].m_timers.empty())
                return;

            iMsgThread* thd = (iMsgThread*)iThreadMgr::spawn_this();
            std::list<iTimerObject::iTimerObjectEntry> tmp;
            m_to[m_cursor].m_timers.swap(tmp);
			for(std::list<iTimerObject::iTimerObjectEntry>::iterator iter=tmp.begin();iter!=tmp.end();++iter)
			{
				if(iter->metrics)
				{
					m_timer_wheel->add_timer(iter->tmr, iter->metrics);
				}
				else
				{
					iter->tmr->m_launcher->post_msg(iMsg::new_instance(MSG_TIMER, iter->tmr, iter->tmr->m_launcher), thd);
					iter->tmr->m_param.loop--;
					if(iter->tmr->m_param.loop)
					{
						iter->tmr->m_param.loop += iter->tmr->m_param.loop==0xFFFFFFFF ? 1:0;
                        m_timer_wheel->add_timer(iter->tmr, iter->tmr->m_param.interval>>4);
					}
					else
						iter->tmr->m_stopped = true;
				}
			}
		}
		inline void put(iTimer* tmr, uint8_t dail, uint32_t metrics)
		{
			iTimerObject::iTimerObjectEntry toe = {tmr, metrics};
			dail += m_cursor;
			//printf("dail=%d,metrics=%d\n", dail, metrics);
			m_to[dail].m_timers.push_back(toe);
		}

	private:
		iTimerObject  m_to[256];
		uint8_t		  m_cursor;
		iTimerMeter*  m_next;
		iTimerWheel*  m_timer_wheel;
	};

	iTimerMeter	m_meter[4];
};

class iTimerThread : public iMsgThread
{
public:
	void add_timer(iTimer* tmr)
	{
		if(tmr)
			post_msg(iMsg::new_instance(MSG_ADD_TIMER, tmr, this), (iMsgThread*)iThreadMgr::spawn_this());
	}

protected:
	virtual int on_message(iMsgID msg, void* param);
	virtual int run();

private:
	iTimerWheel m_timer_wheel;
};

#endif  //__ILIB_CORE_TIMER_THREAD_20120413__
